#ifndef _BASE_NODE_HPP
#define _BASE_NODE_HPP 1

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/signal.h>
//#include <linux/socket.h>
#include <sys/select.h>
#include <strings.h>
#include <errno.h>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include "../util/Role.hpp"
#include "../membership/Membership.hpp"
#include "../Parameters.hpp"
#include "../messages/MacArrayMessage.hpp"
#include "../messages/MacMessage.hpp"

namespace BFT
{
  class BaseNode //: public BFT::network::MessageHandler
  {
	
	
  public:
		
    BaseNode(BFT::util::Role _myrole, boost::shared_ptr<BFT::membership::Membership> _membership);
    ~BaseNode();
		
    //sends a message contained in the char* wrapped by the shared_ptr _bytes and of size _bytes_size
    //to the replica role.id
    //returns the number of bytes sent or a negative value in case of error
    // if sending to self, returns immediately (without sending) the _bytes_size
    int sendToNode(boost::shared_ptr<char> _bytes, int _bytes_size, BFT::util::Role _role, int _id);
		
    int sendToClient(boost::shared_ptr<char> _bytes, int _bytes_size,int _id);
    int sendToOrder(boost::shared_ptr<char> _bytes, int _bytes_size,int _id);
    int sendToExec(boost::shared_ptr<char> _bytes, int _bytes_size,int _id);
    int sendToFilter(boost::shared_ptr<char> _bytes, int _bytes_size,int _id);
		
    int sendToAllClients(boost::shared_ptr<char> _bytes, int _bytes_size);
    int sendToAllOrder(boost::shared_ptr<char> _bytes, int _bytes_size);
    int sendToAllExec(boost::shared_ptr<char> _bytes, int _bytes_size);
    int sendToAllFilter(boost::shared_ptr<char> _bytes, int _bytes_size);
		
    int sendToAllRole(BFT::util::Role _role, boost::shared_ptr<char> _bytes, int _bytes_size);
		
    int sendToAll(boost::shared_ptr<char> _bytes, int _bytes_size);
		
    //TODO
    bool validateClientMacArrayMessage(boost::shared_ptr<BFT::messages::MacArrayMessage>);		
    //TODO
    bool validateExecMacArrayMessage(boost::shared_ptr<BFT::messages::MacArrayMessage>);
    //TODO
    bool validateOrderMacArrayMessage(boost::shared_ptr<BFT::messages::MacArrayMessage>);
    // TODO
    void authenticateExecMacArrayMessage(boost::shared_ptr<BFT::messages::MacArrayMessage> _mam);
    // TODO
    void authenticateOrderMacArrayMessage(boost::shared_ptr<BFT::messages::MacArrayMessage> _mam);
    // TODO
    void authenticateExecMacMessage(boost::shared_ptr<BFT::messages::MacMessage> _mam, int _index);
    //TODO
    bool validateExecMacMessage(boost::shared_ptr<BFT::messages::MacMessage>);
    // TODO
    void authenticateOrderMacMessage(boost::shared_ptr<BFT::messages::MacMessage> _mam, int _index);
    //TODO
    bool validateOrderMacMessage(boost::shared_ptr<BFT::messages::MacMessage>);		
						
    int getMyId(); //inlined
		
    boost::shared_ptr<BFT::membership::Membership> getMembership(); //inlined

    int getMyClientIndex();
    int getMyOrderIndex();
    int getMyExecutionIndex();
    int getMyFilterIndex();
		
  protected:
				
    boost::shared_ptr<BFT::membership::Membership> membership;
    BFT::util::Role myRole;
		
  private:

    //pointers to vectors of socket, used to send messages to other principals
    // different pointer for each category
    int* to_client;
    int* to_order;
    int* to_exec;
    int* to_filter;	 
		
    int myid;
    boost::mutex send_mutex;
  };
	
  inline int BFT::BaseNode::getMyId() {return myid;}
  inline boost::shared_ptr<BFT::membership::Membership> BaseNode::getMembership() {return membership;}
	
}//namespace BFT

#endif
